﻿using FileTransfer.Vollk;
using FileTransfer.Vollk.Model;
using HAF.FtpUtility;
using HAF.FtpUtility.Enum;
using HAF.FtpUtility.Model;
using HAF.LogUtility;
using HAF.LogUtility.Except;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;

namespace FileTransfer.Assistantor
{
    /// <summary>
    /// 资源采集器
    /// </summary>
    [DisplayName("资源采集器")]
    public class MediaGather : PushMessageable, IDisposable
    {
        #region 运行参数
        /// <summary>
        /// 下载队列文件
        /// </summary>
        List<SiteFileStruct> _downQueueFiles;
        /// <summary>
        /// 下载记录
        /// </summary>
        List<FileDownRecordStuct> _fileDownRecords = new List<FileDownRecordStuct>();
        /// <summary>
        /// 运行控制通用配置
        /// </summary>
        GatherParams _runConfig;
        /// <summary>
        /// FTP站点配置
        /// </summary>
        SiteLinkParameter _siteConfig;
        /// <summary>
        /// 输出日志名称
        /// </summary>
        string _logName;
        /// <summary>
        /// 文件格式
        /// </summary>
        string[] _fileFormats;

        #endregion 运行参数

        public void Dispose()
        {
            if (_downQueueFiles != null)
            {
                _downQueueFiles.Clear();
                _downQueueFiles = null;
            }

            if (_fileDownRecords != null)
            {
                _fileDownRecords.Clear();
                _fileDownRecords = null;
            }
        }

        #region 扩展代理事件
        /// <summary>
        /// 采集结束事件
        /// </summary>
        public Action<bool, string> GatherEndEvent;
        /// <summary>
        /// 表单刷新事件
        /// </summary>
        public Action<List<SiteFileStruct>> RefreshGridEvent;
        public Action<string> WriteStripCaptionEvent;
        public Action<string, int> WriteProcessEvnet;
        /// <summary>
        /// 文件下载状态输出
        /// </summary>
        public Action<string, long, long, long, long> DownloadChangeEvent;

        private void RefreshGrid(List<SiteFileStruct> files)
        {
            if (RefreshGridEvent != null)
            {
                RefreshGridEvent(files);
            }
        }

        private void RefreshStripCaption(string caption)
        {
            if (WriteStripCaptionEvent != null)
            {
                WriteStripCaptionEvent(caption);
            }
        }

        private void GatherEnd(bool result, string msg)
        {
            if (GatherEndEvent != null)
            {
                GatherEndEvent(result, msg);
            }
        }
        #endregion 扩展代理事件

        public MediaGather():this(new GatherParams()) { }

        public MediaGather(GatherParams controlParams)
        {
            _runConfig = controlParams;
            _downQueueFiles = new List<SiteFileStruct>();
        }

        public void Down(SiteTaskConfig downConfig)
        {
            if (downConfig == null)
            {
                ShowErrMessage("下载参数异常");
                return;
            }
            if (_runConfig != null)
            {
                _siteConfig = downConfig;
                _fileFormats = downConfig.Controller.FileFormats == null || downConfig.Controller.FileFormats.Length == 0 ?  _runConfig.Formats : downConfig.Controller.FileFormats;
                _logName = string.Format("{0}{1}", downConfig.Tag, DateTime.Now.Ticks);
                PatchDownThrad(downConfig.Tag, downConfig.Controller.FileFormats, downConfig.FileSets);
            }
            else
            {
                ShowErrMessage("配置文件加载异常");
                return;
            }
        }

        /// <summary>
        /// 批量介质下载处理线程
        /// </summary>
        /// <param name="siteName">站点标签</param>
        /// <param name="preFormats">格式限定</param>
        /// <param name="preFiles">待下载任务集合</param>
        private void PatchDownThrad(string siteName, string[] preFormats, List<SiteFileStruct> preFiles)
        {
            ShowInfoMessage(string.Format("当前站点{0}共有{1}个介质等待下载", siteName, preFiles.Count));

            int i = 1;
            //获取所有需下载文件（当前下载任务可能包括目录）
            foreach (var item in preFiles)
            {
                ShowDebugMessage(string.Format("加载第{0}个文件{1}到执行队列", i, item.RemoteFileName));
                if (item.IsDirectory)
                {
                    ShowDebugMessage(string.Format("获取远端目录{0}下的所有文件", item.RemoteFileName));
                    GetDirectoryFiles(siteName, item.RemoteRootDirectory, item.RemoteFileName);
                }
                else
                {
                    bool formatCheck = false;
                    //获取文件扩展名并进行校验
                    string tmpExtName = string.IsNullOrEmpty(item.ResExtName) ? Path.GetExtension(item.RemoteFileName) : item.ResExtName;
                    if (preFormats != null && preFormats.Length > 0)
                    {
                        foreach (var itemExt in preFormats)
                        {
                            if (tmpExtName.ToLower().Equals(itemExt.ToLower()))
                            {
                                formatCheck = true;
                                break;
                            }
                        }
                    }
                    else
                    {
                        formatCheck = true;
                    }

                    if (formatCheck)
                    {
                        //解决目录和文件名都有关键字导致的重复采集问题
                        SiteFileStruct tmpFile = _downQueueFiles.Find(t => t.RemoteFileName == item.RemoteFileName);
                        if (tmpFile == null)
                        {
                            _downQueueFiles.Add(new SiteFileStruct()
                            {
                                ID = item.ID,
                                Site = item.Site,
                                CreateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                                IsDirectory = false,
                                Name = item.Name,
                                ResExtName = item.ResExtName,
                                //DirectoryName = item.DirectoryName,
                                RemoteFileName = item.RemoteFileName,
                                //ResSaveFullPath = item.ResSaveFullPath,
                                ResSaveDirectory = item.ResSaveDirectory,
                                //Size = item.Size
                            });
                        }
                    }
                    else
                    {
                        ShowErrMessage("文件格式校验失败{0}", item.ResExtName);
                    }
                }

                i++;
            }

            DownFiles(siteName);
        }

        private void GetDirectoryFiles(string cpName, string dirName, string remotePath)
        {
            using (FluentFtpHelper ftpClient = new FluentFtpHelper(_siteConfig))
            {
                ftpClient.LogOutName = _logName;
                ftpClient.WriteConsoleMessageEvent = WriteConsoleMessageEvent;
                ftpClient.DownloadProcessChangeEvent = WriteProcessEvnet;
                ftpClient.DownloadChangeEvent = DownloadChangeEvent;
                //获取目录下所有文件
                List<SiteFileStruct> fdrs = ftpClient.GetDirectorieFiles(remotePath);
                if (fdrs != null && fdrs.Count > 0)
                {
                    foreach (var subItem in fdrs)
                    {
                        //subItem.DirectoryName = dirName; // item.DirectoryName;
                        //subItem = cpName;
                    }
                    foreach (var itemExt in _fileFormats)
                    {
                        _downQueueFiles.AddRange(fdrs.FindAll(t => t.ResExtName.ToLower().Equals(itemExt.ToLower())));
                    }
                }

            }
        }

        private void DownFiles(string cpName)
        {
            //校验待下载文件
            //_fileDownRecords = FileAssistantor.GetContentProviderFileRecords(cpName);
            //ShowDebugMessage("当前CP{0}下载记录数据共有{1}个，已下载完成{2}个", cpName, _fileDownRecords.Count, _fileDownRecords.FindAll(t => t.State == (int)TransferCode.Success).Count);

            List<FileDownRecordStuct> tmpDownRecords = new List<FileDownRecordStuct>();
            foreach (var item in _downQueueFiles)
            {
                RefreshStripCaption(string.Concat(" 准备下载", item.RemoteFileName));

                //item.LocalPath = GetLocalFullName(item.RemotePath, item.DirectoryName);
                //下载记录处理
                FileDownRecordStuct tmpFdr = _fileDownRecords.Find(t => t.RemoteName == item.RemoteFileName);
                //在下载记录中未找到已下载记录
                if (tmpFdr == null)
                {
                    //_fileDownRecords.Add(new FileDownRecordStuct() { FileName = item.RemotePath, State = TransferCode.Init });
                    FileDownRecordStuct tmpRecord = new FileDownRecordStuct()
                    {
                        CPName = cpName,
                        FileName = item.Name,
                        RemoteName = item.RemoteFileName,
                        //SaveName = item.ResSaveFullPath,
                        GatherTime = DateTime.Now,
                        //FileSize = item.IsDirectory ? 0 : item.Size,
                        State = (int)TransferCode.Success
                    };
                    tmpDownRecords.Add(tmpRecord);
                    _fileDownRecords.Add(tmpRecord);
                    item.BEnable = true;
                }
                else
                {
                    //如果下载记录存在
                    item.BEnable = tmpFdr.State != (int)TransferCode.Success;
                }
            }

            int iRemoved = _downQueueFiles.RemoveAll(t => t.BEnable == false);
            ShowDebugMessage(string.Format("当前CP[{0}]删除已下载的任务{1}个，尚有{2}个任务等待处理", cpName, iRemoved, _downQueueFiles.Count));
            //需下载数据入库
            //FileAssistantor.AppendContentProviderFileRecords(cpName, tmpDownRecords);
            //输出到表格
            RefreshGrid(_downQueueFiles);
            try
            {
                //启动下载
                using (FluentFtpHelper ftpClien = new FluentFtpHelper(_siteConfig))
                {
                    ftpClien.LogOutName = _logName; // _runConfig.CpName + DateTime.Now.Ticks.ToString();
                    ftpClien.WriteConsoleMessageEvent = WriteConsoleMessageEvent;
                    ftpClien.ReportMessageEvent = null;
                    ftpClien.DownloadProcessChangeEvent = WriteProcessEvnet;
                    ftpClien.DownloadChangeEvent = DownloadChangeEvent;
                    ftpClien.DownloadEndEvent = GatherEnd;

                    //注意：Path.Combine使用时，后续的地址不能加/或者//
                    //string localPath = Path.Combine(_runConfig.SaveDir, dateStr, cpName);
                    ftpClien.DownPatchFiles(_downQueueFiles);
                }
            }
            catch (RunException e)
            {
                ShowErrMessage(e.ErrorMessage);
            }
            
        }

        /// <summary>
        /// 任务采集完成处理
        /// </summary>
        /// <param name="taskId">下载任务编号</param>
        /// <param name="state">下载任务状态</param>
        private void GatherEnd(string taskId, int state)
        {
            ShowDebugMessage(string.Format("下载任务{0}处理完成{1}", taskId, state));
            if (_downQueueFiles != null && _downQueueFiles.Count > 0)
            {
                SiteFileStruct file = _downQueueFiles.Find(t => t.ID == taskId);
                if (file != null)
                {
                    ShowDebugMessage(file.ResExtName);
                    //如果当前文件是M3U8文件，则需要下载M3u8列表中的所有ts文件到本地
                    if (file.ResExtName.ToLower().IndexOf("m3u8") > 0)
                    {
                        ShowInfoMessage("启动M3U8下载验证 site {2} RemotePath {0} LocalPath {1}", file.RemoteFileName, file.RemoteRootDirectory, _siteConfig.Host);
                        M3u8TaskModel taskData = new M3u8TaskModel()
                        {
                            TaskID = Guid.NewGuid().ToString("N"),
                            M3u8Url = string.Format("{0}/{1}", _siteConfig.ToString(), file.RemoteFileName),
                            M3u8Path = file.ResSaveDirectory,
                            LocalDirectory = LoadContext.DefaultSaveAddress,
                            SubUrl = new List<TsEntity>()
                        };
                        M3u8TaskAssistant m3U8Task = new M3u8TaskAssistant(taskData);
                        m3U8Task.DownParts();
                    }
                    //FileAssistantor.SetContentProviderFileRecordState(file.CpName, file.RemotePath, state);
                }
            }

            GatherEndEvent?.Invoke(false, "");
        }
    }
}
